<Project>
  <PropertyGroup>
    <RunScriptWindowsCmd Condition="'$(TargetOS)' == 'windows' and '$(RunScriptWindowsCmd)' == ''">true</RunScriptWindowsCmd>
    <RunScriptWindowsCmd Condition="'$(TargetOS)' != 'windows' and '$(RunScriptWindowsCmd)' == ''">false</RunScriptWindowsCmd>
  </PropertyGroup>
  <PropertyGroup Condition="'$(RunScriptInputName)' == ''">
    <RunScriptInputName Condition="'$(RunScriptWindowsCmd)' == 'true'">RunnerTemplate.cmd</RunScriptInputName>
    <RunScriptInputName Condition="'$(RunScriptWindowsCmd)' != 'true'">RunnerTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(BuildTestsOnHelix)' == 'true' and '$(TargetsAppleMobile)' == 'true'">AppleHelixRunnerTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(BuildTestsOnHelix)' != 'true' and '$(TargetsAppleMobile)' == 'true'">AppleRunnerTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetOS)' == 'android'">AndroidRunnerTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetOS)' == 'wasi' and '$(OS)' != 'Windows_NT' and '$(BuildAOTTestsOnHelix)' == 'true'">WasiRunnerAOTTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetOS)' == 'wasi' and '$(OS)' != 'Windows_NT' and '$(BuildAOTTestsOnHelix)' != 'true'">WasiRunnerTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetOS)' == 'wasi' and '$(OS)' == 'Windows_NT'">WasiRunnerTemplate.cmd</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetOS)' == 'browser' and '$(OS)' != 'Windows_NT' and '$(BuildAOTTestsOnHelix)' == 'true'">WasmRunnerAOTTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetOS)' == 'browser' and '$(OS)' != 'Windows_NT' and '$(BuildAOTTestsOnHelix)' != 'true'">WasmRunnerTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetOS)' == 'browser' and '$(OS)' == 'Windows_NT'">WasmRunnerTemplate.cmd</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetsLinuxBionic)' == 'true' and '$(RunScriptWindowsCmd)' != 'true'">BionicRunnerTemplate.sh</RunScriptInputName>
    <RunScriptInputName Condition="'$(TargetsLinuxBionic)' == 'true' and '$(RunScriptWindowsCmd)' == 'true'">BionicRunnerTemplate.cmd</RunScriptInputName>
    <InnerRunScriptInputName>BionicRunOnDevice.sh</InnerRunScriptInputName>
  </PropertyGroup>

  <PropertyGroup>
    <RunScriptInputPath Condition="'$(RunScriptInputPath)' == ''">$(MSBuildThisFileDirectory)$(RunScriptInputName)</RunScriptInputPath>
    <InnerRunScriptInputPath>$(MSBuildThisFileDirectory)$(InnerRunScriptInputName)</InnerRunScriptInputPath>

    <RunScriptOutputName Condition="'$(RunScriptWindowsCmd)' != 'true'">RunTests.sh</RunScriptOutputName>
    <RunScriptOutputName Condition="'$(BuildTestsOnHelix)' == 'true' and '$(TargetsAppleMobile)' == 'true'">build-apple-app.sh</RunScriptOutputName>
    <RunScriptOutputName Condition="'$(RunScriptWindowsCmd)' == 'true' or (('$(TargetOS)' == 'browser' or '$(TargetOS)' == 'wasi') and '$(OS)' == 'Windows_NT')">RunTests.cmd</RunScriptOutputName>
    <InnerRunScriptOutputName>$(AssemblyName).sh</InnerRunScriptOutputName>
    <RunScriptOutputPath>$([MSBuild]::NormalizePath('$(OutDir)', '$(RunScriptOutputName)'))</RunScriptOutputPath>
    <InnerRunScriptOutputPath>$([MSBuild]::NormalizePath('$(OutDir)', '$(InnerRunScriptOutputName)'))</InnerRunScriptOutputPath>
    <InnerRunEnvOutputPath>$([MSBuild]::NormalizePath('$(OutDir)', 'TestEnv.txt'))</InnerRunEnvOutputPath>

    <RunScriptHostDir Condition="'$(RunScriptWindowsCmd)' == 'true'">%RUNTIME_PATH%\</RunScriptHostDir>
    <RunScriptHostDir Condition="'$(RunScriptWindowsCmd)' != 'true'">$RUNTIME_PATH/</RunScriptHostDir>

    <RunScriptHost Condition="'$(RunScriptWindowsCmd)' == 'true'">$(RunScriptHostDir)dotnet.exe</RunScriptHost>
    <RunScriptHost Condition="'$(RunScriptWindowsCmd)' != 'true'">$(RunScriptHostDir)dotnet</RunScriptHost>
  </PropertyGroup>

  <PropertyGroup>
    <!-- Default and user defined categories -->
    <_withCategories Condition="'$(WithCategories)' != ''">;$(WithCategories.Trim(';'))</_withCategories>
    <_withoutCategories Condition="'$(WithoutCategories)' != ''">;$(WithoutCategories.Trim(';'))</_withoutCategories>

    <TestScope Condition="'$(TestScope)' == '' and '$(Outerloop)' == 'true'">all</TestScope>
    <_withCategories Condition="'$(TestScope)' == 'outerloop'">$(_withCategories);OuterLoop</_withCategories>
    <_withoutCategories Condition="'$(ArchiveTests)' == 'true'">$(_withoutCategories);IgnoreForCI</_withoutCategories>
    <_withoutCategories Condition="'$(TestScope)' == '' or '$(TestScope)' == 'innerloop'">$(_withoutCategories);OuterLoop</_withoutCategories>
    <_withoutCategories Condition="!$(_withCategories.Contains('failing'))">$(_withoutCategories);failing</_withoutCategories>
  </PropertyGroup>

  <!-- For both tests.mobile.targets and tests.wasm.targets -->
  <PropertyGroup>
    <_MonoAotCrossCompilerPath>$([MSBuild]::NormalizePath($(MonoAotCrossDir), 'mono-aot-cross'))</_MonoAotCrossCompilerPath>
    <_MonoAotCrossCompilerPath Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">$(_MonoAotCrossCompilerPath).exe</_MonoAotCrossCompilerPath>
  </PropertyGroup>
  <ItemGroup>
    <MonoAotCrossCompiler Include="$(_MonoAotCrossCompilerPath)" RuntimeIdentifier="$(TargetOS)-$(TargetArchitecture.ToLowerInvariant())" />
  </ItemGroup>

  <PropertyGroup>
    <ArchiveTestsAfterTargets>PrepareForRun</ArchiveTestsAfterTargets>

    <!-- For browser we need to hook up the target with DependsOnTargets in PublishTestAsSelfContained
    because we do a Publish which runs after Build, if we run after PrepareForRun we would generated
    an empty zip because we haven't published the selfcontained app.  -->
    <ArchiveTestsAfterTargets Condition="'$(TargetOS)' == 'browser' or '$(TargetOS)' == 'wasi' or '$(TestSingleFile)' == 'true'" />
  </PropertyGroup>

  <ItemGroup Condition="'$(IsXUnitLogCheckerSupported)' == 'true' and
                        '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
                         $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '$(NETCoreAppCurrentVersion)'))">
    <SetScriptCommands Condition="'$(TargetOS)' == 'windows'" Include="set __IsXUnitLogCheckerSupported=1" />
    <SetScriptCommands Condition="'$(TargetOS)' != 'windows'" Include="export __IsXUnitLogCheckerSupported=1" />
  </ItemGroup>

  <!-- Archive test binaries. -->
  <Target Name="ArchiveTests"
          Condition="'$(ArchiveTests)' == 'true' and '$(IgnoreForCI)' != 'true' and ('$(TargetsMobile)' != 'true' or '$(TargetOS)' == 'browser' or '$(TargetOS)' == 'wasi' or '$(BuildTestsOnHelix)' == 'true')"
          AfterTargets="$(ArchiveTestsAfterTargets)"
          DependsOnTargets="GenerateRunScript;ZipTestArchive" />
  
  <Target Name="ZipTestArchive"
          Condition="'$(TargetsAppleMobile)' != 'true'">
    <Error Condition="'$(TestArchiveTestsDir)' == ''" Text="TestArchiveTestsDir property to archive the test folder must be set." />

    <PropertyGroup>
      <_ZipSourceDirectory>$(OutDir)</_ZipSourceDirectory>
      <_ZipSourceDirectory Condition="'$(TargetOS)' == 'browser' or '$(TargetOS)' == 'wasi' or '$(TestSingleFile)' == 'true'">$(BundleDir)</_ZipSourceDirectory>
    </PropertyGroup>

    <MakeDir Directories="$(TestArchiveTestsDir)" />
    <ZipDirectory SourceDirectory="$(_ZipSourceDirectory)"
                  DestinationFile="$([MSBuild]::NormalizePath('$(TestArchiveTestsDir)', '$(TestProjectName).zip'))"
                  Overwrite="true" />
    <!-- delete the BundleDir and PublishDir in CI builds to save disk space on build agents since they're no longer needed -->
    <RemoveDir Condition="'$(ContinuousIntegrationBuild)' == 'true'" Directories="$(BundleDir)" ContinueOnError="WarnAndContinue" />
    <RemoveDir Condition="'$(ContinuousIntegrationBuild)' == 'true' and '$(OS)' != 'Windows_NT'" Directories="$(PublishDir)" ContinueOnError="WarnAndContinue" />
  </Target>

  <UsingTask TaskName="GenerateRunScript" AssemblyFile="$(InstallerTasksAssemblyPath)"/>
  <Target Name="GenerateRunScript">
    <PropertyGroup>
      <!-- RSP file support. -->
      <RunScriptCommand Condition="'$(RunScriptWindowsCmd)' != 'true' and (('$(TargetOS)' != 'browser' and '$(TargetOS)' != 'wasi') or '$(OS)' != 'Windows_NT')">$(RunScriptCommand) $RSP_FILE</RunScriptCommand>
      <RunScriptCommand Condition="'$(RunScriptWindowsCmd)' == 'true' or (('$(TargetOS)' == 'browser' or '$(TargetOS)' == 'wasi') and '$(OS)' == 'Windows_NT')">$(RunScriptCommand) %RSP_FILE%</RunScriptCommand>

      <!-- Escape potential user input. -->
      <RunScriptCommand>$([MSBuild]::Escape('$(RunScriptCommand)'))</RunScriptCommand>
    </PropertyGroup>

    <!-- Set $(TestDebugger) to eg c:\debuggers\windbg.exe to run tests under a debugger. -->
    <PropertyGroup Condition="'$(TestDebugger)' != ''">
      <RunScriptCommand Condition="!$(TestDebugger.Contains('devenv'))">$(TestDebugger) $(RunScriptCommand)</RunScriptCommand>
      <RunScriptCommand Condition=" $(TestDebugger.Contains('devenv'))">$(TestDebugger) /debugexe $(RunScriptCommand)</RunScriptCommand>
    </PropertyGroup>

    <ItemGroup>
      <!--
        If the PreExecutionTestScript property is set, then it should be set to the full path to a script that will be directly incorporated
        into the generated runtests script, immediately before the test is run. This can be used to set a number of JIT stress modes,
        for example. It is intended that this be as late as possible in the generated script, as close as possible to the running of the
        test. That is why this doesn't appear higher in this file. The idea is that if the included script alters managed code behavior, such as
        setting various JIT stress modes, we don't want those changes to affect any other managed code invocation (such as test infrastructure
        written in managed code).
      -->
      <RunScriptCommands Condition="'$(PreExecutionTestScript)' != ''" Include="$([System.IO.File]::ReadAllText('$(PreExecutionTestScript)'))" />

      <RunScriptCommands Include="$(RunScriptCommand)" />

      <!-- Do not put anything between this and the GenerateRunScript invocation. -->
      <RunScriptCommands Include="@(PostRunScriptCommands)" />
    </ItemGroup>

    <PropertyGroup Condition="'$(RunScriptOutputDirectory)' != ''">
      <RunScriptOutputPath>$([MSBuild]::NormalizePath('$(RunScriptOutputDirectory)', '$(RunScriptOutputName)'))</RunScriptOutputPath>
    </PropertyGroup>

    <GenerateRunScript RunCommands="@(RunScriptCommands)"
                       SetCommands="@(SetScriptCommands)"
                       TemplatePath="$(RunScriptInputPath)"
                       OutputPath="$(RunScriptOutputPath)" />

    <Exec Condition="'$(TargetOS)' != 'windows' and '$(OS)' != 'Windows_NT'" Command="chmod +x $(RunScriptOutputPath)" />
    <Copy Condition="'$(TargetsLinuxBionic)' == 'true'" SourceFiles="$(InnerRunScriptInputPath)" DestinationFiles="$(InnerRunScriptOutputPath)" />
    <Exec Condition="'$(TargetsLinuxBionic)' == 'true' and '$(OS)' != 'Windows_NT'" Command="chmod +x $(InnerRunScriptOutputPath)" />

    <PropertyGroup Condition="'$(TargetsLinuxBionic)' == 'true'">
      <_AndroidArchitecture Condition="'$(TargetArchitecture)' == 'x64'">x86_64</_AndroidArchitecture>
      <_AndroidArchitecture Condition="'$(TargetArchitecture)' == 'x86'">x86</_AndroidArchitecture>
      <_AndroidArchitecture Condition="'$(TargetArchitecture)' == 'arm64'">arm64-v8a</_AndroidArchitecture>
      <_AndroidArchitecture Condition="'$(TargetArchitecture)' == 'arm'">armeabi-v7a</_AndroidArchitecture>
      <_BionicTestEnv>
ASSEMBLY_NAME=$(AssemblyName).dll
TEST_ARCH=$(_AndroidArchitecture)
      </_BionicTestEnv>
    </PropertyGroup>

    <WriteLinesToFile Condition="'$(TargetsLinuxBionic)' == 'true'" File="$(InnerRunEnvOutputPath)" Overwrite="true" Lines="$(_BionicTestEnv)" Encoding="ascii">
    </WriteLinesToFile>
  </Target>

  <Target Name="RunTests">
    <PropertyGroup Condition="'$(TargetsMobile)' != 'true'">
      <RunTestsCommand>"$(RunScriptOutputPath)"</RunTestsCommand>
      <!-- Use runtime path only for the live built shared framework (NetCoreAppCurrent). -->
      <RunTestsCommand Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
                                  $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '$(NETCoreAppCurrentVersion)'))">$(RunTestsCommand) --runtime-path "$(NetCoreAppCurrentTestHostPath.TrimEnd('\/'))"</RunTestsCommand>
      <RunTestsCommand Condition="'$(TestRspFile)' != '' and '$(RuntimeFlavor)' != 'Mono'">$(RunTestsCommand) --rsp-file "$(TestRspFile)"</RunTestsCommand>
    </PropertyGroup>

    <PropertyGroup Condition="'$(TargetsMobile)' == 'true'">
      <RunTestsCommand>"$(RunScriptOutputPath)" $(AssemblyName) $(TargetArchitecture) $(TargetOS) $(TestProjectName)</RunTestsCommand>
      <RunTestsCommand Condition="'$(TargetsAppleMobile)' == 'true'">$(RunTestsCommand) $(Configuration) $(AdditionalXHarnessArguments)</RunTestsCommand>
      <RunTestsCommand Condition="'$(TargetOS)' == 'android'">$(RunTestsCommand) $(AdditionalXHarnessArguments)</RunTestsCommand>
      <RunTestsCommand Condition="'$(TargetOS)' == 'browser'">"$(RunScriptOutputPath)" $(JSEngine) $(AssemblyName).dll $(Scenario)</RunTestsCommand>
    </PropertyGroup>

    <!-- Invoke the run script with the test host as the runtime path. -->
    <Exec Command="$(RunTestsCommand)"
          ContinueOnError="true"
          IgnoreExitCode="true"
          IgnoreStandardErrorWarningFormat="true">
      <Output PropertyName="TestRunExitCode" TaskParameter="ExitCode" />
    </Exec>

    <PropertyGroup Condition="'$(TestRunExitCode)' != '0'">
      <TestResultsPath>$(OutputPath)$(TestResultsName)</TestResultsPath>
      <TestRunErrorMessage>One or more tests failed while running tests from '$(TestProjectName)'.</TestRunErrorMessage>
      <TestRunErrorMessage Condition="Exists('$(TestResultsPath)')">$(TestRunErrorMessage) Please check $(TestResultsPath) for details!</TestRunErrorMessage>
    </PropertyGroup>

    <Error Condition="'$(TestRunExitCode)' != '0'" Text="$(TestRunErrorMessage)" />
  </Target>

  <Import Project="$(MSBuildThisFileDirectory)tests.mobile.targets" Condition="'$(TargetsMobile)' == 'true'" />
  <Import Project="$(MSBuildThisFileDirectory)tests.singlefile.targets" Condition="'$(TestSingleFile)' == 'true'" />
  <Import Project="$(MSBuildThisFileDirectory)xunit\xunit.targets" Condition="'$(TestFramework)' == 'xunit'" />

  <!-- Main test targets -->
  <Target Name="Test" DependsOnTargets="$(TestDependsOn)" />

  <Import Project="$(MSBuildThisFileDirectory)outerBuild.targets" Condition="'$(IsCrossTargetingBuild)' == 'true'" />
</Project>
